/**
 * 得到允许js访问的cookie串的json对象
 *
 * @returns cookie的json对象
 */
function fnGetCookieJson() {
    let json = {};
    let cookieStr = document.cookie.trim(); //对于服务端设置为HttpOnly的cookie是无法通过js取到的
    if (!cookieStr) {
        return json;
    }
    let cookies = cookieStr.split(";");
    for (let i in cookies) {
        let cookie = cookies[i].trim().split("=");
        json[cookie[0].trim()] = cookie[1].trim();
    }
    return json;
}

/**
 * 显示图片
 *
 * @param {File} file 图片文件
 * @param {Element} imgEle 显示图片的img元素
 * @param {number} limit 大小限制kb
 * @returns 是否显示成功
 */
function fnShowImg(file, imgEle, limit) {
    if (!file.files[0]) {
        return false;
    }
    if (limit && file.files[0].size > limit * 1024) {
        alert("图片大小超过限制，请重新选择！");
        return false;
    }
    let fileReader = new FileReader();
    fileReader.readAsDataURL(file.files[0]); //这种方法可以把blob读为base64
    fileReader.onload = function (e) {
        imgEle.src = this.result;
    };
    return true;
}

/**
 * 发起ajax异步请求
 *
 * @param {string} methodType 请求方法类型 GET 或 POST
 * @param {string} url 请求地址
 * @param {FormData|string} param formData对象或参数串
 * @param {function} fnSuc 成功回调函数
 * @param {function} fnFail 失败回调函数
 */
function fnAjax(methodType, url, param, fnSuc, fnFail) {
    let wholeUrl = "http://" + location.host + url;
    let xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
        if (xhr.responseURL && xhr.responseURL != location.href && xhr.responseURL != wholeUrl) {
            location.href = xhr.responseURL; //视为有重定向
        }
        switch (xhr.readyState) {
            case 4:
                if (xhr.status >= 200 && xhr.status < 300) {
                    if (fnSuc) { //成功回调
                        fnSuc(xhr.responseText);
                    }
                } else {
                    alert(xhr.responseText); //注意，若请求不会重定向，务必以POST方式，否则服务端报错时会返回一个完整的显错页面
                    if (fnFail) { //失败回调
                        fnFail(xhr.responseText);
                    }
                }
                break;
        }
    }
    xhr.open(methodType, wholeUrl);
    if (param && typeof (param) != "string") { //FormData对象时转为参数串
        prmStr = "";
        param.forEach((v, k) => prmStr += k + "=" + v + "&");
        param = prmStr.substring(0, prmStr.length - 1);
    }
    xhr.send(encodeURIComponent(param)); //注意编码
}

/**
 * 往聊天记录表插数据
 *
 * @param {json} rowData 行数据
 */
function fnInsertHistory(rowData) {
    doIdxDB(function (db, tableName) {
        let transaction = db.transaction(tableName, "readwrite").objectStore(tableName).add(rowData);
        transaction.onerror = function (e) {
            console.log(e);
            alert("indexedDB 写入失败：" + e.target.error.message);
        };
        transaction.onsuccess = function (e) {};
    });
}

/** 可能作为查询条件的全部组合的索引名 */
var idxName = [null, "idx_isImg", "idx_username", "idx_user_img", "idx_date", "idx_date_img", "idx_date_user", "idx_date_user_img"];
/**
 * 查询聊天记录
 *
 * @param {date} historyDate 日期
 * @param {string} username 发送者
 * @param {boolean} onlyImg 是否仅查图片
 * @param {function} _fnSucc 成功回调
 */
function fnQueryHistory(historyDate, username, onlyImg, _fnSucc) {
    let condition = (historyDate ? 1 : 0) * 4 + (username ? 1 : 0) * 2 + (onlyImg == "true" ? 1 : 0);
    let getQuery = function () {
        switch (condition) { //目前只能这样蛋疼地实现多条件组合查询
            case 1:
                return "true";
            case 2:
                return username;
            case 3:
                return [username, "true"];
            case 4:
                return historyDate;
            case 5:
                return [historyDate, "true"];
            case 6:
                return [historyDate, username];
            case 7:
                return [historyDate, username, "true"];
        };
    };
    doIdxDB(function (db, tableName) { //打开数据库
        let table = db.transaction(tableName, "readwrite").objectStore(tableName);
        let getAll;
        if (condition > 0) {
            getAll = table.index(idxName[condition]).getAll(IDBKeyRange.only(getQuery())); //选了哪些条件，就以对应的索引查
        } else {
            getAll = table.getAll();
        }
        getAll.onerror = function (e) {
            console.log(e);
            alert("indexedDB getAll 方法失败：" + e.target.error.message);
        };
        getAll.onsuccess = function (e) {
            if (_fnSucc) {
                _fnSucc(getAll.result);
            }
        };
    });
}

/**
 * 查询聊天历史记录中有的所有用户以生成条件下拉
 *
 * @param {function} _fnSucc 查询完毕后的操作
 */
function fnQueryUsers(_fnSucc) {
    doIdxDB(function (db, tableName) {
        let resultSet = [];
        let openCursor = db.transaction(tableName, "readwrite").objectStore(tableName).index("idx_username").openKeyCursor(null, "nextunique"); //nextunique类似distinct
        openCursor.onerror = function (e) {
            console.log(e);
            alert("indexedDB 打开游标失败：" + e.target.error.message);
        };
        openCursor.onsuccess = function (e) {
            let cursor = e.target.result
            if (cursor) { //以“唯一”模式遍历游标，逐个放入数组
                resultSet.push(cursor.key);
                cursor.continue();
            } else if (_fnSucc) { //遍历完毕后传递数组至回调
                _fnSucc(resultSet);
            }
        };
    });
}

/**
 * 打开聊天记录IndexedDB并对聊天记录表做操作
 *
 * @param {function} _fn 打开IDB数据库后要做的回调，将传入数据库对象及表名
 */
function doIdxDB(_fn) {
    let db;
    let tableName = "t_chat";
    let conn = indexedDB.open("chatDB");
    conn.onerror = function (e) {
        console.log(e);
        alert("indexedDB 打开错误：" + e.target.error.message);
    };
    conn.onsuccess = function (e) { //已经建有数据库时走本事件
        db = conn.result;
        _fn(db, tableName);
    };
    conn.onupgradeneeded = function (e) { //初次建数据库后走本事件
        db = e.target.result;
        if (!db.objectStoreNames.contains(tableName)) { //建表及索引
            let table = db.createObjectStore(tableName, {
                autoIncrement: true
            });
            //目前只能这样实现组合条件查询
            table.createIndex("idx_date", "date");
            table.createIndex("idx_username", "username");
            table.createIndex("idx_isImg", "isImg");
            table.createIndex("idx_date_user", ["date", "username"]);
            table.createIndex("idx_date_img", ["date", "isImg"]);
            table.createIndex("idx_user_img", ["username", "isImg"]);
            table.createIndex("idx_date_user_img", ["date", "username", "isImg"]);
        }
        doIdxDB(_fn);
    };
}